#include "asm_utils.h"
#include "interrupt.h"
#include "stdio.h"
#include "program.h"
#include "thread.h"
#include "sync.h"

// 屏幕IO处理器
STDIO stdio;
// 中断管理器
InterruptManager interruptManager;
// 程序管理器
ProgramManager programManager;

//Semaphore semaphore;
Semaphore empty;	//柜台上可以摆放的食品数量
Semaphore mutex;	//缓冲区互斥信号量,代表一个缓冲区
Semaphore A ;	       //薯条数量
Semaphore B ;	       //炸鸡数量
int a=0;int b=0;	       //表示炸鸡和薯条的数量
int producerclock=1e8;

void producer1(void *arg){
        empty.P();
        mutex.P();
        printf("producer1:   I have made 1 French fries!\n");
        a++;
        printf("------ French fries: %d ; Fired chicken: %d -------\n",a,b);
        mutex.V();
        A.V();
        
}

void producer2(void *arg){
	empty.P();
        mutex.P();
        printf("producer2:   I have made 1 Fired chicken!\n");
        b++;
        printf("------ French fries: %d ; Fired chicken: %d -------\n",a,b);
        mutex.V();
        B.V();
}

void consumer1(void *arg)
{
    A.P();
    mutex.P();
    printf("consumer1   : I want French fries!\n");
    // get French fries
    //A -= 1;
    // leave
    a--;
    printf("------ French fries: %d ; Fired chicken: %d -------\n",a,b);
    mutex.V();
    empty.V();
}

void consumer2(void *arg)
{
    B.P();
    mutex.P();
    printf("consumer2   : I want Fired chichken!\n");
    // get fired chicken
    //B -= 1;
    // leave
    b--;
    printf("------ French fries: %d ; Fired chicken: %d -------\n",a,b);
    mutex.V();
    empty.V();
}

void consumer3(void *arg)
{
    A.P();
    B.P();
    mutex.P();
    printf("consumer3   : I want both\n");
    //A--;B--
    a--;
    b--;
    printf("------ French fries: %d ; Fired chicken: %d -------\n",a,b);
    mutex.V();
    empty.V();empty.V();
}

void producer(void *arg){  
    while (1)	{
    	producerclock--;
    	if (producerclock==0)	{
    	    producerclock=1e8;
    	    programManager.executeThread(producer1,nullptr,"forth thread",1);
    	    programManager.executeThread(producer2,nullptr,"fifth thread",1);
    	}
    }
}

void consumer(void *arg)	{
    programManager.executeThread(consumer1, nullptr, "sixth thread", 1);
    programManager.executeThread(consumer2, nullptr, "seventh thread", 1);
    programManager.executeThread(consumer3, nullptr, "eighth thread", 1);
}


void first_thread(void *arg)
{
    // 第1个线程不可以返回,下面循环是清屏操作
    stdio.moveCursor(0);
    for (int i = 0; i < 25 * 80; ++i)
    {
        stdio.print(' ');
    }
    stdio.moveCursor(0);

    empty.initialize(4);  
    mutex.initialize(1);
    A.initialize(0);
    B.initialize(0);
	
    programManager.executeThread(producer, nullptr, "second thread", 1);
    programManager.executeThread(consumer, nullptr, "third thread", 1);

    asm_halt();
}

extern "C" void setup_kernel()
{

    // 中断管理器
    interruptManager.initialize();
    interruptManager.enableTimeInterrupt();
    interruptManager.setTimeInterrupt((void *)asm_time_interrupt_handler);

    // 输出管理器
    stdio.initialize();

    // 进程/线程管理器
    programManager.initialize();

    // 创建第一个线程
    int pid = programManager.executeThread(first_thread, nullptr, "first thread", 1);
    if (pid == -1)
    {
        printf("can not execute thread\n");
        asm_halt();
    }

    ListItem *item = programManager.readyPrograms.front();
    PCB *firstThread = ListItem2PCB(item, tagInGeneralList);
    firstThread->status = RUNNING;
    programManager.readyPrograms.pop_front();
    programManager.running = firstThread;
    asm_switch_thread(0, firstThread);

    asm_halt();
}
